package com.sinosoft.brokerchannel.base.rest;

import com.sinosoft.brokerchannel.base.common.ChannelConstants;
import com.sinosoft.brokerchannel.base.server.AbstractService;
import com.sinosoft.brokerchannel.base.utile.BusinessException;
import com.sinosoft.brokerchannel.base.utile.BusinessUtils;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * 需求名称：[经纪公司渠道平台]<br/>
 * 类描述:[Controller控制层的基础类]<br/>
 *
 * @author shilk
 * @version V1.0
 * @date 2018-8-17 11:57
 */
@Controller
public class AbstractController extends AbstractService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private BusinessUtils businessUtils;

    @Value("${spring.http.encoding.charset}")
    private String charset;

    @Value("${environment.serviceController.contentType}")
    private String contentType;

    /**
     * 对外服务入口
     * 1.对外提供统一入口
     * 2.渠道验证、服务权限验证、请求数据解密。
     * 3.服务路由：根据请求报文Channel（渠道信息）节点下channelTradeCode（渠道交易代码）进行服务路由。
     * 4.异常处理：处理服务层以外的异常，对外提供良好的提示信息。
     *
     * @param request  http请求对象
     * @param response http返回对象
     * @throws Exception
     */
    @RequestMapping(value = {"/", "carchannel"})
    @ApiOperation(value = "外部渠道入口", hidden = true, position = 7)
    public void carchannel(HttpServletRequest request, HttpServletResponse response) {
        try {
            //请求数据解密处理
            String requestBody = businessUtils.decryp(request);
            //请求转发
            request.getRequestDispatcher((String) request.getAttribute("requestDispatcherPath")).forward(this.createServletRequest(request, requestBody, this.charset), response);
        } catch (BusinessException e) {
            logger.info(ChannelConstants.EXCEPTION_LOG, e);
            response.setContentType(contentType);
            response.setCharacterEncoding(charset);
            try {
                response.getWriter().write("业务异常：" + e.getExceptionMessage());
            } catch (IOException e1) {
                System.out.println("================11111111111111111111==============");
                e1.printStackTrace();
            }
        } catch (Exception e) {
            logger.info(ChannelConstants.EXCEPTION_LOG, e);
            response.setContentType(contentType);
            response.setCharacterEncoding(charset);
            try {
                response.getWriter().write("未知异常：请检查请求数据是否正确或者联系运维人员！");
            } catch (IOException e1) {
                System.out.println("================22222222222222222==============");
                e1.printStackTrace();
            }
        } finally {
            try {
                response.getWriter().close();
            } catch (IOException e) {
                System.out.println("================33333333333333333==============");
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建新的ServletRequest对象，替换输入流
     *
     * @param request
     * @param requestBody
     * @param charset
     * @return
     * @throws Exception
     */
    public ServletRequest createServletRequest(HttpServletRequest request, String requestBody, String charset) throws UnsupportedEncodingException {
        return new HttpServletRequestWrapper(request) {
            @Override
            public String getContentType() {
                if (request.getContentType().contains("text/xml")) {
                    return request.getContentType().replace("text/xml", "application/xml");
                }
                return request.getContentType();
            }

            @Override
            public ServletInputStream getInputStream() throws UnsupportedEncodingException {
                return new ServletInputStream() {
                    private byte[] buf;   //请求数据
                    private int pos;      //当前位置
                    private int count;    //数据长度

                    @Override
                    public synchronized int read() {
                        return (pos < count) ? (buf[pos++] & 0xff) : -1;
                    }

                    @Override
                    public boolean isFinished() {
                        return false;
                    }

                    @Override
                    public boolean isReady() {
                        return false;
                    }

                    @Override
                    public void setReadListener(ReadListener listener) {
                    }

                    /**
                     * @param input
                     * @return
                     */
                    public ServletInputStream create(String input) throws UnsupportedEncodingException {
                        try {
                            this.buf = input.getBytes(charset);
                            this.pos = 0;
                            this.count = buf.length;
                        } catch (Exception e) {
                            logger.info(ChannelConstants.ExceptionResult.ERROR.getMessage(), e);
                            throw e;
                        }
                        return this;
                    }
                }.create(requestBody);
            }
        };
    }
}
